package com.heima.article.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.heima.article.entity.ApArticle;
import com.heima.article.service.IApArticleService;
import com.heima.article.service.IHotArticleService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author: itheima
 * @create: 2022-01-24 12:08
 */
@Slf4j
@Service
public class HotArticleServiceImpl implements IHotArticleService {

    @Autowired
    private IApArticleService apArticleService;

    @Autowired
    private StringRedisTemplate redisTemplate;


    /**
     * 查询最近五天用户发布文章列表，对每篇文章得分进行计算，将计算排行榜数据缓存到redis中
     */
    @Override
    public void compute() {
        //1.查询当日凌晨0点前五天的文章数据
        LambdaQueryWrapper<ApArticle> queryWrapper = new LambdaQueryWrapper<>();
        //1.1 查询上架状态  未删除文章
        queryWrapper.eq(ApArticle::getIsDown, false);
        queryWrapper.eq(ApArticle::getIsDelete, false);

        //1.2 设置时间区间
        Date toDate = getFromAndToDate(0);
        Date fromDate = getFromAndToDate(-30);
        queryWrapper.between(ApArticle::getPublishTime, fromDate, toDate);

        //2.遍历文章列表，计算分值
        List<ApArticle> articleList = apArticleService.list(queryWrapper);
        //2.1 定义redis中不同频道key 前缀
        String redisKeyPrefix = "leadnews:article:hot:page:";
        //2.2 遍历文章计算所有文章得分
        for (ApArticle article : articleList) {
            int score = computeScore(article);
            //2.3 构建redis缓存对象-只缓存需要数据
            ApArticle cache = new ApArticle();
            cache.setId(article.getId());
            cache.setTitle(article.getTitle());
            cache.setImages(article.getImages());
            cache.setAuthorId(article.getAuthorId());
            cache.setAuthorName(article.getAuthorName());
            cache.setLayout(article.getLayout());
            cache.setStaticUrl(article.getStaticUrl());
            String value = JSON.toJSONString(cache);
            //3.将计算后热点数据缓存到redis中
            //3.1 按照不同频道将热点数据缓存redis
            String indexKey = redisKeyPrefix + "0";
            redisTemplate.opsForZSet().add(indexKey, value, score);

            String channelKey = redisKeyPrefix + article.getChannelId();
            redisTemplate.opsForZSet().add(channelKey, value, score);

            //3.2 设置过期时间
            redisTemplate.expire(indexKey, 1, TimeUnit.DAYS);
            redisTemplate.expire(channelKey, 1, TimeUnit.DAYS);
        }
    }


    /**
     * 为入参的文章计算分值
     *
     * @param article
     * @return
     */
    private int computeScore(ApArticle article) {
        int score = 0;
        // 阅读 +1  点赞 +3  评论 +5  收藏 +8
        if (article.getViews() != null) {
            score += article.getViews() * 1;
        }
        if (article.getLikes() != null) {
            score += article.getLikes() * 3;
        }
        if (article.getComment() != null) {
            score += article.getComment() * 5;
        }
        if (article.getCollection() != null) {
            score += article.getCollection() * 8;
        }
        return score;
    }


    /**
     * 获取指定天数日期 正数：未来时间  负数：以前时间
     *
     * @param datecount
     * @return
     */
    public static Date getFromAndToDate(Integer datecount) {
        //创建日期对象
        Calendar calendar = Calendar.getInstance();
        //设置日期
        calendar.add(Calendar.DATE, datecount);
        //设置时分秒
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        return calendar.getTime();
    }
}
